import Foundation

/**
 * 功能描述:聊天协议解析工具
 * 修改时间:
 * 修改描述:
 */
public class ProtocolUtil {
    
    public static let ERR_CODE = -1;

    /**
     * 获取接收消息的长度
     *
     * @param buffer tcp收到的消完整息字节数组
     * @return
     */
    public static func getReceiveMsgContentLength( buffer:[UInt8]?) ->Int{
        if (buffer == nil || buffer?.count == 0) {
            return 0;
        }
        /*
         byte[] dataLenByte = new byte[4];
               System.arraycopy(buffer, 5, dataLenByte, 0, 4);
               return byteArrayToInt(dataLenByte);
         */
        let startIndex = 5
        let length = 4
        return byteArrayToInt(buffer: Array(buffer![startIndex ..< startIndex+length]))
        
//        var value : UInt32 = 0
//        let data = NSData(bytes: buffer, length: buffer!.count)
//        data.getBytes(&value, length: buffer!.count)
//        value = UInt32(bigEndian: value)
//        return Int(value)
    }

    /**
     * 获取接收消息的ID
     *
     * @param buffer tcp收到的消完整息字节数组
     * @return
     */
    public static func getReceiveCmdId(buffer:[UInt8]?) ->Int {
        if (buffer == nil || buffer?.count == 0) {
            return ERR_CODE;
        }
//        var msgIdBuffer:[UInt8] = [];
        let startIndex = 0
        let length = 4
        let msgIdBuffer = Array(buffer![startIndex ..< startIndex+length])
//        msgIdBuffer =
       // System.arraycopy(buffer, 0, msgIdBuffer, 0, 4);
        return byteArrayToInt(buffer: msgIdBuffer);
    }

    
    /**
        * 获取服务器推送消息类型
        * <p>
        *
        * @param buffer tcp收到的消完整息字节数组
        * @return 消息类型
        * 0：服务器推送的新消息：{@link com.quwan.imlib.constant.ServerConst#RECEIVED_MSG_TYPE_NEW}
        * 1：服务器响应客户端发送的消息：{@link com.quwan.imlib.constant.ServerConst#RECEIVED_MSG_TYPE_RESP}
        */
    public static func getReceiveMsgType(buffer:[UInt8]?) -> UInt8{
        if (buffer == nil || buffer!.count == 0) {
            return  0;
        }

        let startIndex = 4
        let length = 1
        
        let list = Array(buffer![startIndex ..< startIndex+length]);
        return list[0];
//        return  UInt8(byteArrayToInt(buffer: Array(buffer![startIndex ..< startIndex+length])))


    }
    
    
    /**
     * 获取消息内容
     *
     * @param buffer tcp收到的消完整息字节数组
     * @return
     */
    public static func getReceiveMsgContent(buffer:[UInt8]?) -> String {
        if (buffer == nil || buffer!.count == 0) {
            return "";
        }
        let msgContentLength:Int = getReceiveMsgContentLength(buffer: buffer);
        //System.arraycopy(buffer, 9, dataByte, 0, msgContentLength);
        let startIndex = 9
        let length = msgContentLength
        let msgIdBuffer = Array(buffer![startIndex ..< startIndex+length])
        return String.init(bytes: msgIdBuffer, encoding: .utf8)!//new String(dataByte).trim();
    }

    /**
     * 封装待发送的消息
     *
     * @param id  消息包ID
     * @param msg 消息内容,json格式
     */
    static func packagingToBeSentMsg( id:Int,  msg:String) ->String{
        let buffer = packagingToBeByteArraySentMsg(cmdId: id, msg: msg)
        let data =  Data.init(bytes: buffer, count: buffer.count)
        return  String.init(data: data, encoding: .utf8) ?? ""//String(packagingToBeByteArraySentMsg(cmdId: id, msg: msg)).trim();
    }

    /**
     * 封装待发送的消息
     *
     * @param cmdId 消息包ID
     * @param msg   消息内容,json格式
     */
    public static func packagingToBeByteArraySentMsg(cmdId:Int,  msg:String)->[UInt8] {
//        byte[] body = msg.getBytes();
//        byte[] data = new byte[body.length + 9];
//        byte[] idMsg = ProtocolUtil.intToByteArray(cmdId);
//        byte[] dataLength = ProtocolUtil.intToByteArray(body.length);
//
//        System.arraycopy(idMsg, 0, data, 0, 4);
//        data[4] = 0;
//        System.arraycopy(dataLength, 0, data, 5, 4);
//        System.arraycopy(body, 0, data, 9, body.length);
//        return data;
        
        
        let body = Array(msg.utf8)
        var data:[UInt8]!;
        let idMsg = intToByteArray(integer: cmdId)
        let dataLength = intToByteArray(integer: body.count)
        
        data = Array(idMsg[0 ..< 4])
        data.append(0);
        data.append(contentsOf: Array(dataLength[0..<4]))
        data.append(contentsOf: Array(body[0..<body.count]))
//        let byteArray: [UInt8] = msg.utf8.map{UInt8($0)}
        return data;

    }

    /**
     * 数据类型转换 int转Byte数组
     *
     * @param integer
     * @return
     */
    public static func intToByteArray(integer:Int)->[UInt8] {
//        int byteNum = (40 - Integer.numberOfLeadingZeros(integer < 0 ? ~integer : integer)) / 8;
//        byte[] byteArray = new byte[4];
//
//        for (int n = 0; n < byteNum; n++) {
//            byteArray[3 - n] = (byte) (integer >>> (n * 8));
//        }
//        return byteArray;
        let value : Int32 = Int32(integer)
        let array = withUnsafeBytes(of: value.bigEndian, Array.init)
        return array;
        
        
        /*
         
         https://stackoverflow.com/questions/56964045/how-to-convert-int-to-byte-array-of-4-bytes-in-swift
         
         In Java an integer is always 32-bit, but in Swift it can be 32-bit or 64-bit, depending on the platform. Your code creates a byte array with the same size as that of the Int type, on a 64-bit platform that are 8 bytes.

         If you want to restrict the conversion to 32-bit integers then use Int32 instead of Int, the result will then be an array of 4 bytes, independent of the platform.

         An alternative conversion method is

         let value: Int32 = -1333
         let array = withUnsafeBytes(of: value.bigEndian, Array.init)
         print(array) // [255, 255, 250, 203]
         Or as a generic function for integer type of all sizes:
         
         func byteArray<T>(from value: T) -> [UInt8] where T: FixedWidthInteger {
             withUnsafeBytes(of: value.bigEndian, Array.init)
         }
         Example:
            
         print(byteArray(from: -1333))        // [255, 255, 255, 255, 255, 255, 250, 203]
         print(byteArray(from: Int32(-1333))) // [255, 255, 250, 203]
         print(byteArray(from: Int16(-1333))) // [250, 203]
         */
    }
            
    /**
     * 数据类型转换 byte数组转int
     *
     * @param b
     * @param offset
     * @return
     */
    public static func byteArrayToInt( b:[UInt8],  offset:Int) ->Int {
//        int value = 0;
//        for (int i = 0; i < 4; i++) {
//            int shift = (4 - 1 - i) * 8;
//            value += (b[i + offset] & 0x000000FF) << shift;
//        }
//        return value;
        
        var value : UInt32 = 0
        let data = NSData(bytes:Array(b[offset..<b.count]) , length: b.count-offset)
        data.getBytes(&value, length: b.count)
        value = UInt32(bigEndian: value)
        return Int(value)
    }

    /**
     * 字节数组转int
     *
     * @param buffer
     * @return
     */
    public static func byteArrayToInt(buffer:[UInt8]) ->Int{
//        int value = 0;
//        for (int i = 0; i < 4; i++) {
//            int shift = (4 - 1 - i) * 8;
//            value += (buffer[i] & 0x000000FF) << shift;
//        }
//        return value;
        var value : UInt32 = 0
        let data = NSData(bytes: buffer, length: buffer.count)
        data.getBytes(&value, length: buffer.count)
        value = UInt32(bigEndian: value)
        return Int(value)
    }

}
